// eslint-disable
<style lang="scss" scoped rel="stylesheet/scss">
@import '~@/scss/global/colors.scss';

.is-error {
    .inputCont {
        border-color: #f56c6c;
    }
}

.is-success {
    .inputCont {
        border-color: #67c23a;
    }
}

.inputCont {
    position: relative;
    margin: 0;
    max-width: 100%;
    min-width: 100px;
    flex: 1 0 auto;
    outline: none;
    text-align: left;
    line-height: 30px;
    background: #fff;
    padding: 3px 30px 3px 6px;
    border: 1px solid rgba(34, 36, 38, 0.15);
    color: rgba(0, 0, 0, 0.87);
    border-radius: 0.28571429rem;
    transition: box-shadow 0.1s ease, border-color 0.1s ease;
    box-shadow: none;
    min-height: 40px;

    .placeholder {
        position: absolute;
        left: 10px;
        color: #ccc;
        font-size: 12px;
        margin-top: 2px;
        font-weight: normal;
    }

    &.small,
    &.baseplate.small {
        line-height: 20px;
        padding: 4px 30px 4px 6px;
        min-height: 32px;
    }

    &.mini,
    &.baseplate.mini {
        line-height: 18px;
        padding: 2px 30px 2px 6px;
        min-height: 28px;
    }

    #ellipsis {
        padding-right: 20px;
        padding-left: 10px;
    }
}

.ui.label {
    margin: 2px 4px 2px 0;
    font-weight: normal;
    font-size: 12px;
    display: inline-block;
    position: relative;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;

    &.p-r {
        padding-right: 25px;
    }

    > .delete {
        position: absolute;
        right: 7px;
        top: 50%;
        margin: -5px 0 0 0;
    }

    &.small {
        margin: 0 4px 0 0;
        padding: 4px 25px 2px 2px;
    }

    &.mini {
        margin: 2px 4px 0 0;
        padding: 3px 25px 3px 5px;
    }
}

.icon.circle {
    visibility: hidden;
    right: 1px !important;
    z-index: 99 !important;
    color: #777 !important;
    opacity: 1 !important;
    pointer-events: auto !important;
    cursor: pointer !important;
}

.icon.circle::before {
    font-size: 18px;
    background: #fff !important;
}

.el-dropdown .input:hover .icon.circle {
    visibility: visible;
}

.el-dropdown .icon.circle:hover {
    color: #000 !important;
}

.el-dropdown .q.icon::after {
    color: #000 !important;
    content: attr(quantity);
    margin-left: -14px;
    font-size: 12px;
}

.el-dropdown .baseplate {
    overflow: hidden;
    height: 31px;

    /*white-space:nowrap;*/
    &.small,
    &.mini {
        height: 20px;
    }
}

.el-dropdown .baseplate .inputCont {
    display: none;
}

.el-dropdown .baseplate:hover .popup {
    display: block;
}

//下拉树样式修改
.filter-tree /deep/ .dropdown-tree-node-label {
    flex: 1 !important;
    display: flex !important;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 8px;

    &.act {
        .checkmark.icon {
            visibility: visible;
            color: $content-heightLight;
        }
    }

    .checkmark.icon {
        visibility: hidden;
    }
}

.circular.remove {
    font-size: 12px;
    transform: scale(0.8);
}
</style>
<template>
    <el-dropdown placement="bottom-start" trigger="click" style="width: 100%;display:block">
        <div class="ui fluid icon input">

            <!--用于计算label宽度的隐藏元素-->
            <a class="ui label p-r" id="inner" ref="inner" style="visibility: hidden;position: absolute;z-index: -11"></a>

            <div class="inputCont" :class="size" v-if="!multiple" ref="multiInput">
                <a v-if="selected.label" class="ui label" :class="size" :style="{ width: selected.width }">
                    {{ selected.label }}
                    <i class="delete icon" @click.stop="delItem"></i>
                </a>
                <div class="placeholder" v-if="!selected.label">{{ placeholder }}</div>
                <!--此el-input作用完全是为了触发表单验证-->
                <el-input style="visibility:hidden; position:absolute; left:9999px" v-model="selected.label"></el-input>
            </div>
            <div class="inputCont" :class="size" v-else ref="multiInput">

                <div class="placeholder" v-if="!multiSelected.length || multiSelected.length < 1">{{ placeholder }}</div>
                <div class="baseplate" :class="size" :style="{width:itemW}">
                    <template v-for="item in multiSelected">
                        <a class="ui label p-r" :class="size" :key="item.id" :title="item.label" :style="{ width: item.width }"
                           v-if="item.isShow">
                            {{ item.label }}
                            <i class="delete icon" @click.stop="multiDelItem(item.id, $event)"></i>
                        </a>
                    </template>

                    <a class="ui label ellipsis" :class="size" style="width:30px" v-if="showEllipsis">...</a>
                    <div v-show="popup && collapseTags" class="inputCont popup" :class="size" style="position: absolute; top:0; left: 0;">
                        <a class="ui label" :class="size" :key="item.id" v-for="item in multiSelected">
                            {{ item.label }}
                            <i class="delete icon" @click.stop="multiDelItem(item.id, $event);"></i>
                        </a>
                    </div>
                </div>
            </div>
            <!-- <i class="sitemap icon"></i>-->
            <i class="sitemap icon" v-if="!multiple"></i>
            <i class="q sitemap icon" v-else :quantity="multiSelected.length > 0 ? multiSelected.length : ''"></i>
            <el-tooltip content="清空所选内容" placement="bottom-end" v-if="selected.label || multiSelected.length > 0 ">
                <i class="icon remove circle" @click.stop="clearAll"></i>
            </el-tooltip>
        </div>
        <el-dropdown-menu slot="dropdown" style="width:400px; padding:5px">
            <!--<el-input placeholder="输入关键字进行过滤" v-model="filterText" style="margin-bottom:5px;"></el-input>-->
            <div class="ui fluid icon input">
                <!--<input type="text" v-model="filterText" style="margin-bottom:5px;" placeholder="输入关键字进行过滤">-->
                <el-input placeholder="输入关键字进行过滤" :size="size" v-model="filterText"></el-input>
                <el-tooltip content="清除筛选内容" placement="bottom-end" v-if="filterText.length > 0">
                    <i class="circular remove link icon pos-a" :style="size === 'mini' ? 'top:3px' : ''" @click="filterText = ''"></i>
                </el-tooltip>
            </div>
            <div class="ui scrollbar scroll-no-track m-t-5" style="max-height:250px;">
                <!--单选-->
                <el-tree class="filter-tree" node-key="id" style="border:transparent" :data="treeData" :props="defaultProps"
                         :default-expand-all="collapse" :filter-node-method="filterNode" ref="tree" @node-click="handleNodeClick"
                         :render-content="renderContent" :load="lazyLoad" :lazy="lazy" v-if="!multiple">
                </el-tree>
                <!--多选-->
                <el-tree class="filter-tree" node-key="id" style="border:transparent" show-checkbox :data="treeData" :props="defaultProps"
                         :default-expand-all="collapse" :filter-node-method="filterNode" ref="tree" @check-change="handleNodeChange"
                         :render-content="renderContent" :check-strictly="checkStrictly" :load="lazyLoad" :lazy="lazy" v-else></el-tree>
            </div>
        </el-dropdown-menu>
    </el-dropdown>
</template>
<script type="text/jsx">
export default {
    name : 'ui-dropdown-tree' ,
    props : {
        value : Object ,
        multiple : Boolean ,
        sel : null ,
        dataUrl : String ,
        treeData : null ,
        modelId : null ,
        modelLabel : null ,
        modelCustom : null ,
        size : String ,
        placeholder : String ,
        custom : String ,
        checkStrictly : {
            type : Boolean ,
            default : false
        } ,
        tagEqual : {
            type : Boolean ,
            default : false
        } ,
        collapseTags : {
            type : Boolean ,
            default : false
        } ,
        lazy : {
            type : Boolean ,
            default : false
        } ,
        collapseAll : {
            type : Boolean ,
            default : false
        } ,
        lazyLoad : Function
    } ,
    computed : {
        collapse() {
            if ( this.lazy ) {
                return false
            } else if ( this.collapseAll ) {
                return false
            }

            return true
        }
    } ,
    data() {
        return {
            hideme : null ,
            // multi:typeof this.multiSelect !== 'undefined', //判断是否多选
            selected : '' ,
            multiSelected : {} ,
            checkFlag : true ,
            mIdFlag : true ,
            filterText : '' ,
            itemW : '' ,
            itemH : '' ,
            ellipsis : '' ,
            popup : false ,
            defaultProps : {
                children : 'children' ,
                label : 'label'
            } ,
            isOut : true ,
            showEllipsis : false
        }
    } ,
    watch : {
        filterText( val ) {
            this.$refs.tree.filter( val )
        } ,
        // 初次进入
        treeData() {
            this.init()
        } ,
        // 监听id变化然后执行回显
        modelId( v ) {
            if ( this.mIdFlag ) {
                this.init()
            }
            if ( v === '' && this.isOut ) {
                // 解决筛选器重置数据清空全部节点数据
                this.clearAll()
            }
            this.isOut = true
        }
    } ,
    mounted() {
        this.init()
    } ,
    methods : {
        renderContent( h , { node , data , store } ) {
            if ( this.selected.id === node.data.id ) {
                return this.$scopedSlots.default ? (
                    h(
                        'div' ,
                        { class : 'w-100p' } ,
                        this.$scopedSlots.default( { node : node.data , selected : true } )
                    )
                ) : (
                    <span class="dropdown-tree-node-label act">
            <span>{ node.label }</span>
            <i class="checkmark icon"></i>
          </span>
                )
            } else {
                if ( node.data.disabled ) {
                    return this.$scopedSlots.default ? (
                        h(
                            'div' ,
                            { class : 'w-100p' } ,
                            this.$scopedSlots.default( { node : node.data , selected : false } )
                        )
                    ) : (
                        <span
                            class="dropdown-tree-node-label t-sub"
                            style="cursor:not-allowed;"
                        >
              <span>{ node.label }</span>
              <i class="checkmark icon"></i>
            </span>
                    )
                }
                return this.$scopedSlots.default ? (
                    h(
                        'div' ,
                        { class : 'w-100p' } ,
                        this.$scopedSlots.default( { node : node.data , selected : false } )
                    )
                ) : (
                    <span class="dropdown-tree-node-label">
            <span>{ node.label }</span>
            <i class="checkmark icon"></i>
          </span>
                )
            }
        } ,
        // 根据id递归data中的数据返回 {id :"xxx",label:"xxx"}
        walk( data , id ) {
            if ( !data ) return { id : '' , label : '' }
            for ( let i = 0 , len = data.length ; i < len ; i++ ) {
                let _data = data[ i ]
                if ( _data.id.toString() === id.toString() ) {
                    return _data
                }
                if ( _data.children ) {
                    let n = this.walk( _data.children , id )
                    if ( n !== null ) {
                        return n
                    }
                }
            }
            return null
        } ,
        // 填入初始数据
        init() {
            if ( this.modelId && this.multiple ) {
                //多选情况
                this.$refs.tree.setCheckedKeys( this.modelId.split( ',' ) )
                if ( this.checkFlag ) {
                    this.checkFlag = false
                    setTimeout( () => {
                        // 等setCheckedKeys方法执行完毕才能获得Nodes值
                        this.multiSelected = this.disposeMultiSelected()
                        this.$emit(
                            'update:modelLabel' ,
                            this.$bui.toSQL( this.multiSelected , 'label' )
                        )
                        this.$emit(
                            'update:modelCustom' ,
                            this.$bui.toSQL( this.multiSelected , this.custom )
                        )
                        this.checkFlag = true
                    } )
                }
            } else if ( this.modelId ) {
                //单选情况
                //this.$set(this.value, 'data', { id:this.modelId });
                this.selected = this.walk( this.treeData , this.modelId )
                if ( this.selected ) {
                    //this.$emit('update:modelId', this.selected.id)
                    this.$emit( 'update:modelLabel' , this.selected.label )
                    this.$emit( 'update:modelCustom' , this.selected[ this.custom ] )
                }
            }
        } ,

        filterNode( value , data ) {
            if ( !value ) return true
            // return data.label.indexOf(value) !== -1;
            if ( data.label.indexOf( value ) !== -1 ) {
                return true
            }
            let pinyinCode = data[ 'pinyin_code' ] || data[ 'pinyinCode' ]
            if ( pinyinCode ) {
                let pinyin = pinyinCode.toLocaleUpperCase()
                let val = value.toLocaleUpperCase()
                if ( pinyin.indexOf( val ) !== -1 ) {
                    return true
                }
            }
        } ,
        // 单选
        handleNodeClick( data , node , com ) {
            this.mIdFlag = false
            // 满足can_select条件或是叶子节点才能被选中
            let canSelect = data.can_select || data.canSelect

            // 将当前label文字添加到隐藏元素中来获取实际宽度
            this.disposeSingle( data )

            if ( !data.disabled && ( ( canSelect && canSelect.toString() === '1' ) || node.isLeaf ) ) {
                this.$emit( 'update:modelId' , data.id )
                this.$emit( 'update:modelLabel' , data.label )
                this.$emit( 'update:modelCustom' , data[ this.custom ] )
                // this.$set(this.value, 'data', { id:data.id })
                // 发给回调的参数
                this.$emit( 'change' , {
                    id : data.id ,
                    label : data.label ,
                    custom : data[ this.custom ] ,
                    node : node
                } )
                this.selected = data
            } else {
                let name = com.$el.className.replace( /is-current/ , '' ) //去掉选中后的背景高亮
                // this.sel = this.selected // 为选中对象打勾勾
                setTimeout( () => {
                    com.$el.className = name
                } )
            }
            this.$children[ 0 ].hide()
            //this.init()
        } ,
        // 多选
        handleNodeChange( data , check , com ) {
            this.mIdFlag = false
            if ( this.checkFlag ) {
                this.checkFlag = false
                this.multiSelected = this.disposeMultiSelected()
                this.$emit( 'update:modelId' , this.$bui.toSQL( this.multiSelected , 'id' ) )
                this.$emit(
                    'update:modelLabel' ,
                    this.$bui.toSQL( this.multiSelected , 'label' )
                )
                this.$emit(
                    'update:modelCustom' ,
                    this.$bui.toSQL( this.multiSelected , this.custom )
                )

                // 发给回调的参数
                this.$emit( 'change' , {
                    id : this.$bui.toSQL( this.multiSelected , 'id' ) ,
                    label : this.$bui.toSQL( this.multiSelected , 'label' ) ,
                    custom : this.$bui.toSQL( this.multiSelected , this.custom )
                } )
                this.checkFlag = true
            }
        } ,

        /**
         * 获取隐藏元素和输入框的最大可放label的宽度
         * @returns {{labelLongWidth: number, inner: HTMLAnchorElement}}
         */
        getAttr(labelText) {
            // 隐藏元素用于存放label文本来计算宽度
            const inner = this.$refs.inner
            // 输入框的元素
            let mInput = this.$refs.multiInput
            // 去掉右侧icon的左侧宽度
            const itemW = mInput.clientWidth - 40
            // 左侧可存放label的宽度
            this.itemW = itemW + 'px'
            // 可编辑label的最大宽度, 减去 ellipsis元素的宽度 width：30 + margin-right:4
            const labelLongWidth = itemW - 34
            // 将当前label文字添加到隐藏元素中来获取实际宽度
            inner.innerText = labelText
            let innerWidth = inner.clientWidth + 4
            return { innerWidth  , labelLongWidth }
        } ,

        /**
         * 单选情况，将判断过长设置最大宽度
         * @param data
         */
        disposeSingle( data ) {
            const { innerWidth , labelLongWidth } = this.getAttr(data.label)
            this.$set( data , 'width' , innerWidth > labelLongWidth ? labelLongWidth + 'px' : 'auto' )
        } ,

        /**
         * 处理多选结果是否超长
         */
        disposeMultiSelected() {
            // 每次都都把ellipsis元素隐藏，然后重新计算
            this.showEllipsis = false
            // 获取选中节点状态
            const multiSelected = this.$refs.tree.getCheckedNodes()
            // 已选中的label总宽度
            let allW = 0

            multiSelected.forEach( ( item ) => {

                let { innerWidth , labelLongWidth } = this.getAttr(item.label)

                // 如果当前label宽度大于最大宽度,那么就取最大宽度的2.5
                if ( innerWidth > labelLongWidth ) {
                    innerWidth = Math.floor( labelLongWidth / 2.5 )
                    this.$set( item , 'width' , innerWidth + 'px' )
                } else {
                    this.$set( item , 'width' , 'auto' )
                }

                // 累加当前宽度
                allW += innerWidth

                // 已选中的总宽度 > label的可编辑最大宽度
                // 并控制每个元素的显示隐藏
                if ( allW > labelLongWidth ) {
                    this.$set( item , 'isShow' , false )
                    this.showEllipsis = true
                } else {
                    this.$set( item , 'isShow' , true )
                }
            } )
            return multiSelected
        } ,

        multiDelItem( id , e ) {
            //this.getMultiItem();
            this.$refs.tree.setChecked( id , false , true )
        } ,
        delItem() {
            this.selected = ''

            if ( !this.multiple ) {
                this.isOut = false
                this.$emit( 'update:modelId' , '' )
                this.$emit( 'update:modelLabel' , '' )
                this.$emit( 'update:modelCustom' , '' )
                // 发给回调的参数
                this.$emit( 'change' , { id : '' , label : '' , custom : '' } )
            }
        } ,
        clearAll() {
            this.isOut = false
            this.$refs.tree.setCheckedKeys( [] )
            this.selected = ''
            this.filterText = ''
            this.$children[ 0 ].hide()
            if ( !this.multiple ) {
                this.$emit( 'update:modelId' , '' )
                this.$emit( 'update:modelLabel' , '' )
                this.$emit( 'update:modelCustom' , '' )
                // 发给回调的参数
                this.$emit( 'change' , { id : '' , label : '' , custom : '' } )
            }
        }
    }
}
</script>
